/** 
 * Copyright (c) 2009 Teoti Graphix, LLC See:
 *     http://tkarchitecture.teotigraphix.org
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author Michael Schmalle mschmalle@teotigraphix.com
 */
package org.teotigraphix.dx.patterns.behavior
{

import flash.events.Event;
import flash.events.IEventDispatcher;

import mx.events.PropertyChangeEvent;

import org.teotigraphix.dx.core.ToolKitUtil;
import org.teotigraphix.dx.event.BehaviorLayerEvent;
import org.teotigraphix.dx.event.ChromeEvent;
import org.teotigraphix.dx.event.ComponentLayerEvent;
import org.teotigraphix.dx.event.ModelLayerEvent;
import org.teotigraphix.dx.event.SkinEvent;
import org.teotigraphix.dx.interfaces.IActivate;
import org.teotigraphix.dx.interfaces.IBehaviorLayer;
import org.teotigraphix.dx.interfaces.IComponentAware;
import org.teotigraphix.dx.interfaces.IComponentBehavior;
import org.teotigraphix.dx.interfaces.IComponentLayer;
import org.teotigraphix.dx.interfaces.IComponentLayerClient;
import org.teotigraphix.dx.interfaces.IComponentModel;
import org.teotigraphix.dx.interfaces.IComponentModelCore;
import org.teotigraphix.dx.interfaces.ICoreSkinAware;
import org.teotigraphix.dx.interfaces.IModelLayer;
import org.teotigraphix.dx.interfaces.IToolKitComponent;
import org.teotigraphix.dx.patterns.component.DXContainer;
import org.teotigraphix.dx.patterns.manager.BehaviorManager;
import org.teotigraphix.dx.patterns.manager.ModelManager;
import org.teotigraphix.dx.patterns.manager.meta.ClassMetaData;
import org.teotigraphix.dx.patterns.manager.meta.ComponentAliasInfo;
import org.teotigraphix.dx.patterns.manager.meta.ComponentHandlerInfo;
import org.teotigraphix.dx.patterns.manager.meta.ModelAliasInfo;
import org.teotigraphix.dx.patterns.manager.meta.ModelHandlerInfo;
import org.teotigraphix.dx.patterns.manager.meta.SkinHandlerInfo;
import org.teotigraphix.dx.patterns.manager.meta.SkinPartAliasInfo;
import org.teotigraphix.dx.patterns.manager.meta.SkinPartHandlerInfo;

//--------------------------------------
//  Class
//--------------------------------------

/**
 * A runtime behavior that is added or removed from a Component's
 * <code>behaviorLayer</code>.
 * 
 * <p>This class also acts as the base for the <code>CoreComponentBehavior</code>.
 * The component's <code>coreBehavior</code> is the behavioral abstraction
 * in it's core generalization heiarchy.</p>
 * 
 * @copyright Teoti Graphix, LLC
 * @author Michael Schmalle
 * @date 12-04-08
 */
public class ComponentBehavior 
	   implements IComponentBehavior, IComponentAware, IComponentLayerClient,
	   			  IActivate
{
	include "../../core/Version.as"
	
	//--------------------------------------------------------------------------
	//
	//  Protected Namespace :: Variables
	//
	//--------------------------------------------------------------------------
	
	/**
	 * The namespace for [ComponentHandler] metadata handlers.
	 * 
	 * <p>Use this namespace when defining event handlers in subclasses for 
	 * the Component [ComponentHandler] metadata.</p>
	 * 
	 * <p>The events will be dispatched from a Component and listened to
	 * on this <code>ComponentBehavior</code>.</p>
	 * 
	 * @example
	 * <listing version="3.0">
	 * package com.example.behavior
	 * {
	 * 
	 * [ComponentHandler(event="titleChanged", handler="titleLabelHandler")]
	 * 
	 * class MyTitleBarBehavior extends ComponentBehavior
	 * {
	 *     ...
	 * 
	 *     component_handler function titleLabelHandler(event:Event):void
	 *     {
	 *         titleLabel.text = titleBar.title;
	 *     }
	 * }
	 * }
	 * </listing>
	 */
	protected namespace component_handler = "http://tkarchitecture.teotigraphix.org/component_handler";
	
	/**
	 * The namespace for [ModelHandler] metadata handlers.
	 * 
	 * <p>Use this namespace when defining event handlers in subclasses for 
	 * the Model [ModelHandler] metadata.</p>
	 * 
	 * <p>The events will be dispatched from a Model and listened to
	 * on this <code>ComponentBehavior</code>.</p>
	 * 
	 * @example
	 * <listing version="3.0">
	 * package com.example.behavior
	 * {
	 * 
	 * [ModelHandler(event="mouseCaptureChanged", handler="mouseCaptureHandler")]
	 * 
	 * class MyTitleBarBehavior extends ComponentBehavior
	 * {
	 *     ...
	 * 
	 *     model_handler function mouseCaptureHandler(event:Event):void
	 *     {
	 *         if (!model.mouseCaptured)
	 *             removeSystemMouseHandlers();
	 *     }
	 * }
	 * }
	 * </listing>
	 */
	protected namespace model_handler = "http://tkarchitecture.teotigraphix.org/model_handler";
	
	/**
	 * The namespace for [SkinHandler] metadata handlers.
	 * 
	 * <p>Use this namespace when defining event handlers in subclasses for 
	 * the Skin [SkinHandler] metadata.</p>
	 * 
	 * <p>The events will be dispatched from a Skin and listened to
	 * on this <code>ComponentBehavior</code>.</p>
	 * 
	 * @example
	 * <listing version="3.0">
	 * package com.example.behavior
	 * {
	 * 
	 * [SkinHandler(event="mouseOver", handler="mouseOverHandler")]
	 * 
	 * class MyTitleBarBehavior extends ComponentBehavior
	 * {
	 *     ...
	 * 
	 *     skin_handler function mouseOverHandler(event:MouseEvent):void
	 *     {
	 *         trace("mouseOver event dispatched from the component.skin");
	 *     }
	 * }
	 * }
	 * </listing>
	 */
	protected namespace skin_handler = "http://tkarchitecture.teotigraphix.org/skin_handler";	
	
	/**
	 * The namespace for [SkinPartHandler] metadata handlers.
	 * 
	 * <p>Use this namespace when defining event handlers in subclasses for 
	 * the Skin's subcomponent [SkinPartHandler] metadata.</p>
	 * 
	 * <p>The events will be dispatched from a Skin's subcomponent part and 
	 * listened to on this <code>ComponentBehavior</code>.</p>
	 * 
	 * @example
	 * <listing version="3.0">
	 * package com.example.behavior
	 * {
	 * 
	 * class MyTitleBarBehavior extends ComponentBehavior
	 * {
	 *     [SkinPartHandler(event="click", handler="closeButtonClickHandler")]
	 *     [SkinPartAlias]
	 *     public var closeButton:Button;
	 * 
	 *     ...
	 * 
	 *     skinpart_handler function closeButtonClickHandler(event:MouseEvent):void
	 *     {
	 *         trace("click event dispatched from the closeButton");
	 *         trace(event.target.selected);
	 *     }
	 * }
	 * }
	 * </listing>
	 */
	protected namespace skinpart_handler = "http://tkarchitecture.teotigraphix.org/skinpart_handler";
	
	//--------------------------------------------------------------------------
	//
	// Private :: Variables
	//
	//--------------------------------------------------------------------------

	/**
	 * @private
	 * Set in the constructor of the class does not want to call certain 'Added'
	 * methods.
	 */
	protected var componentHandlers:Array =
	[
		PropertyChangeEvent.PROPERTY_CHANGE,
		// layerActivated(), layerDeactivated()
		ComponentLayerEvent.LAYER_ACTIVATE,
		ComponentLayerEvent.LAYER_DEACTIVATE,
		// volitale :: called in setComponent() and listened to on Component
		// skinAdded(), skinRemoved()
		SkinEvent.SKIN_ADD,
		SkinEvent.SKIN_REMOVE,
		
		ChromeEvent.CHROME_ADD,
		ChromeEvent.CHROME_REMOVE,
		
		// behaviorAdded(), behaviorRemoved()
		BehaviorLayerEvent.BEHAVIOR_ADD,
		BehaviorLayerEvent.BEHAVIOR_REMOVE,
		// modelAdded(), modelRemoved()
		ModelLayerEvent.MODEL_ADD,
		ModelLayerEvent.MODEL_REMOVE
	];
	
	//--------------------------------------------------------------------------
	//
	//  Private :: Variables
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @private
	 */
	private var oldSkin:IEventDispatcher;
	
	//--------------------------------------------------------------------------
	//
	//  Protected :: Properties
	//
	//--------------------------------------------------------------------------

	//----------------------------------
	//  classMetaData
	//----------------------------------
	
	/**
	 * @private
	 */
	private var _classMetaData:ClassMetaData;
	
	/**
	 * The cached class metadata, loaded once in the constructor and cached in 
	 * the <code>MetaManager</code>.
	 * 
	 * @see org.teotigraphix.dx.patterns.manager.MetaManager
	 */
	protected function get classMetaData():ClassMetaData
	{
		return _classMetaData;
	}
	
	/**
	 * @private
	 * Used internally by unit tests.
	 */
	dx_internal function getClassMetaData():ClassMetaData
	{
		return _classMetaData;
	}

	//----------------------------------
	//  behaviorLayer
	//----------------------------------
	
	// TODO (mschmalle) Figure out the best way to implement behaviorLayer
	
	/**
	 * @private
	 */
	protected function get behaviorLayer():IBehaviorLayer
	{
		return BehaviorManager.getBehaviorLayer(component);
	}

	//----------------------------------
	//  modelLayer
	//----------------------------------
	
	// TODO (mschmalle) Figure out the best way to implement modelLayer
	
	/**
	 * @private
	 */
	protected function get modelLayer():IModelLayer
	{
		return ModelManager.getModelLayer(component);
	}
	
	//--------------------------------------------------------------------------
	//
	//  IActivate API :: Properties
	//
	//--------------------------------------------------------------------------
	
	//----------------------------------
	//  isActive
	//----------------------------------
	
	/**
	 * @private
	 */
	private var _isActive:Boolean = false;

	/**
	 * @copy org.teotigraphix.dx.interfaces.IComponentLayer#isActive
	 * 
	 * @uses #commitComponent()
	 */
	public function get isActive():Boolean
	{
		return _isActive;
	}
	
	//--------------------------------------------------------------------------
	//
	//  IComponentAware API :: Properties
	//
	//--------------------------------------------------------------------------

	//----------------------------------
	//  component
	//----------------------------------
	
	/**
	 * @private
	 */
	private var _component:IEventDispatcher;
	
	/**
	 * @copy org.teotigraphix.dx.interfaces.IComponentAware#component
	 * 
	 * @uses #setComponent()
	 */
	public function get component():IEventDispatcher
	{
		return _component;
	}
	
	/**
	 * @private
	 */	
	public function set component(value:IEventDispatcher):void
	{
		if (value != _component)
			setComponent(value);
	}
	
	//----------------------------------
	//  className
	//----------------------------------
	
	/**
	 * @private
	 */
	private var _className:String;
	
	/**
	 * @copy org.teotigraphix.dx.interfaces.IComponentAware#className
	 */
	public function get className():String
	{
		return _className;
	}
	
	//--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Constructor.
	 */
	public function ComponentBehavior()
	{
		_className = ToolKitUtil.getClassName(this);
		_classMetaData = ToolKitUtil.resolveClassMetaData(this);
	}
	
	//--------------------------------------------------------------------------
	//
	//  IActivate API :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @copy org.teotigraphix.dx.interfaces.IActivate#activate()
	 */
	public function activate(host:IEventDispatcher):void
	{
		_isActive = true;
	}
	
	/**
	 * @copy org.teotigraphix.dx.interfaces.IActivate#activate()
	 */
	public function deactivate(host:IEventDispatcher):void
	{
		_isActive = false;
	}
	
	//--------------------------------------------------------------------------
	//
	//  Protected :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Adds or removes the behavior from/to the Component.
	 * 
	 * <p>If there is an existing Component attachment;</p>
	 * 
	 * <ul>
	 * <li>Remove skin handlers.</li>
	 * <li>Remove skin part handlers.</li>
	 * <li>Remove skin part references.</li>
	 * <li>Remove component handlers.</li>
	 * <li>Remove component references.</li>
	 * </ul>
	 * 
	 * <p>If the <code>hostComponent</code> is not null;</p>
	 * 
	 * <ul>
	 * <li>Add component handlers.</li>
	 * <li>Add component references.</li>
	 * </ul>
	 * 
	 * <p>If the <code>hostComponent.skin</code> is not null;</p>
	 * 
	 * <ul>
	 * <li>Add skin handlers.</li>
	 * <li>Add skin part handlers.</li>
	 * <li>Add skin part references.</li>
	 * </ul>
	 * 
	 * @param hostComponent The component that will host this behavior in it's
	 * <code>behaviorLocator</code> or it's <code>coreBehavior</code>.
	 * 
	 * @uses #skinRemoved()
	 * @uses #removingBehavior()
	 * @uses #addingBehavior()
	 * @uses #skinAdded()
	 */
	protected function setComponent(hostComponent:IEventDispatcher):void
	{
		// TODO (mschmalle) get rid of SkinnableComponent
		// if we are currently attached to a element 
		// unplug our behavioral attachments
		if (_component)
		{
			skinRemoved(ICoreSkinAware(_component).coreSkin);
			removingBehavior(_component);
		}
		
		// set the new value of the element
		_component = hostComponent;
		
		// if the component is being set to null, exit
		if (!_component)
			return;
		
		// plugin our behavioral attachments
		addingBehavior(_component);
		// TODO (mschmalle) this might not be needed or at leaset keep some type of
		// cache where you know what has come in and what is going out as
		// far as the skin is concerned
		// if the component's skin is created 
		if (_component is ICoreSkinAware && ICoreSkinAware(_component).coreSkin)
		{
			skinAdded(ICoreSkinAware(_component).coreSkin);
		}
	}
	
	//--------------------------------------------------------------------------
	//
	//  Protected :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Adds the Behavior to the Component.
	 * 
	 * @param instance The Component adding this Behavior.
	 * 
	 * @uses #attachOrDetatchComponentAliases()
	 * @uses #addOrRemoveComponentHandlers()
	 */
	protected function addingBehavior(instance:IEventDispatcher):void
	{
		if (!instance)
			return;
		
		attachOrDetatchComponentAliases(instance, true);
		addOrRemoveComponentHandlers(instance, true);
		addOrRemoveModelAliases(instance, true);
		
		if (_component is DXContainer)
		{
//			__attachOrDetachSkinPartAliases(UIComponent(_component), true);
		}
	}
	
	/**
	 * Removes the Behavior from the Component.
	 * 
	 * @param instance The Component removing this Behavior.
	 * 
	 * @uses #attachOrDetatchComponentAliases()
	 * @uses #addOrRemoveComponentHandlers()
	 */
	protected function removingBehavior(instance:IEventDispatcher):void
	{
		if (!instance)
			return;
		
		attachOrDetatchComponentAliases(instance, false);
		addOrRemoveComponentHandlers(instance, false);
		addOrRemoveModelAliases(instance, false);
		
		if (_component is DXContainer)
		{
//			__attachOrDetachSkinPartAliases(UIComponent(_component), false);
		}		
	}
	
	//--------------------------------------------------------------------------
	//
	//  Protected Added/Removed Override :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @private
	 */
	protected function layerActivated(layer:IComponentLayer):void
	{
	}
	
	/**
	 * @private
	 */
	protected function layerDeactivated(layer:IComponentLayer):void
	{
	}
	
	/**
	 * Adds the Skin to the Behavior.
	 * 
	 * @param skin The Skin being added.
	 * 
	 * @uses #addOrRemoveSkinHandlers()
	 * @uses #attachOrDetachSkinPartAliases()
	 */
	protected function skinAdded(skin:IEventDispatcher):void
	{
		oldSkin = skin;
		addOrRemoveSkinHandlers(skin, true);
		attachOrDetachSkinPartAliases(skin, true);
	}
	
	/**
	 * Removes the Skin from the Behavior.
	 * 
	 * @param skin The Skin being removed.
	 * 
	 * @uses #addOrRemoveSkinHandlers()
	 * @uses #attachOrDetachSkinPartAliases()
	 */
	protected function skinRemoved(skin:IEventDispatcher):void
	{
		addOrRemoveSkinHandlers(skin, false);
		attachOrDetachSkinPartAliases(skin, false);
	}
	
	/**
	 * Adds the chrome to the Behavior.
	 * 
	 * @param host The host being added.
	 * 
	 * @uses #addOrRemoveSkinHandlers()
	 * @uses #__attachOrDetachSkinPartAliases()
	 */
	protected function chromeAdded(host:IEventDispatcher):void
	{
		addOrRemoveSkinHandlers(host, true);
		attachOrDetachSkinPartAliases(host, true);
	}
	
	/**
	 * Removes the chrome from the Behavior.
	 * 
	 * @param host The host being removed.
	 * 
	 * @uses #addOrRemoveSkinHandlers()
	 * @uses #attachOrDetachSkinPartAliases()
	 */
	protected function chromeRemoved(host:IEventDispatcher):void
	{
		addOrRemoveSkinHandlers(host, false);
		attachOrDetachSkinPartAliases(host, false);
	}
	
	/**
	 * Called when a skin part is added to the component.
	 * 
	 * @param partName The string part name of the instance being added.
	 * @param instance The object reference of the instance being added.
	 */
	protected function partAdded(partName:String, instance:Object):void
	{
	}
	
	/**
	 * Called when a skin part is removed from the component.
	 * 
	 * @param partName The string part name of the instance being removed.
	 * @param instance The object reference of the instance being removed.
	 */
	protected function partRemoved(partName:String, instance:Object):void
	{
	}
	
	/**
	 * Called when the <code>component.behaviorLayer</code> has it's
	 * <code>registerBehavior()</code> method executed or called when the
	 * <code>component.coreBehavior</code> property has been assigned.
	 * 
	 * @param api The Class api used to key the registered 
	 * <code>IComponentBehavior</code>.
	 * @param The registered <code>IComponentBehavior</code>.
	 */
	protected function behaviorAdded(api:Class, behavior:IComponentBehavior):void
	{
	}
	
	/**
	 * Called when the <code>component.behaviorLayer</code> has it's
	 * <code>removeBehavior()</code> method executed or called when the
	 * <code>component.coreBehavior</code> property has been unassigned.
	 * 
	 * @param api The Class api used to key the remove 
	 * <code>IComponentBehavior</code>.
	 * @param The removed <code>IComponentBehavior</code>.
	 */
	protected function behaviorRemoved(api:Class, behavior:IComponentBehavior):void
	{
	}
	
	/**
	 * Called when the <code>component.modelLayer</code> has it's
	 * <code>registerModel()</code> method executed or called when the
	 * <code>component.coreModel</code> property has been assigned.
	 * 
	 * @param api The Class api used to key the registered 
	 * <code>IComponentModel</code>.
	 * @param The registered <code>IComponentModel</code>.
	 */
	protected function modelAdded(api:Class, service:IComponentModel):void
	{
	}
	
	/**
	 * Called when the <code>component.modelLayer</code> has it's
	 * <code>removeModel()</code> method executed or called when the
	 * <code>component.coreModel</code> property has been unassigned.
	 * 
	 * @param api The Class api used to key the remove 
	 * <code>IComponentModel</code>.
	 * @param The removed <code>IComponentModel</code>.
	 */
	protected function modelRemoved(api:Class, service:IComponentModel):void
	{
	}
	
	//----------------------------------
	//  [ComponentHandler]
	//----------------------------------
	
	/**
	 * @private
	 * Add or remove the [ComponentHandler] from the behavior.
	 */
	protected function addOrRemoveComponentHandlers(
		component:IEventDispatcher, add:Boolean):void 
	{
		for each(var directive:ComponentHandlerInfo in classMetaData.componentHandlers) 
		{
			var handler:Function = this.component_handler::[directive.handler];
			if (add)
				ToolKitUtil.addEventHandler(component, handler, directive);
			else
				ToolKitUtil.removeEventHandler(component, handler, directive);
		}
		
		var i:int = 0;
		var len:int = componentHandlers.length;
		
		for (i = 0; i < len; i++)
		{
			var type:String = componentHandlers[i];
			if (add)
				component.addEventListener(type, this[type + "Handler"]);
			else
				component.removeEventListener(type, this[type + "Handler"]);
		}
	}
	
	//----------------------------------
	//  [ModelHandler]
	//----------------------------------
	
	/**
	 * @private
	 * Add or remove the [ModelHandler] from the behavior.
	 */
	protected function addOrRemoveModelHandlers(
		model:IEventDispatcher, add:Boolean):void 
	{
		for each(var directive:ModelHandlerInfo in classMetaData.modelHandlers) 
		{
			var handler:Function = this.model_handler::[directive.handler];

			if (add)
				ToolKitUtil.addEventHandler(model, handler, directive);
			else
				ToolKitUtil.removeEventHandler(model, handler, directive);
		}
	}
	
	//----------------------------------
	//  [SkinHandler]
	//----------------------------------
	
	/**
	 * @private
	 * Add or remove the classMetaData.skinHandlers to the instance.
	 */
	protected function addOrRemoveSkinHandlers(
		skin:IEventDispatcher, add:Boolean):void
	{
		for each(var directive:SkinHandlerInfo in classMetaData.skinHandlers)
		{
			var handler:Function = this.skin_handler::[directive.handler] as Function;
			
			if (add)
				ToolKitUtil.addEventHandler(skin, handler, directive);
			else
				ToolKitUtil.removeEventHandler(skin, handler, directive);
		}
	}
	
	//----------------------------------
	//  [SkinPartAlias][SkinPartHandler]
	//----------------------------------
	
	/**
	 * @private
	 * Add or remove the [Part][PartHandler] from the composite part instances.
	 */
	protected function addOrRemovePartHandlers(
		part:IEventDispatcher, add:Boolean):void 
	{
		for each(var directive:SkinPartHandlerInfo in classMetaData.skinPartHandlers) 
		{
			if (this[directive.dispatcher] !== part)
				continue;
			
			var handler:Function = this.skinpart_handler::[directive.handler];
			
			if (add)
				ToolKitUtil.addEventHandler(part, handler, directive);
			else
				ToolKitUtil.removeEventHandler(part, handler, directive);
		}
	}
	
	//----------------------------------
	//  [ComponentAlias]
	//----------------------------------
	
	/**
	 * @private
	 * Adds or removes the classMetaData.componentAliases to the behavior.
	 */	
	protected function attachOrDetatchComponentAliases(
		instance:IEventDispatcher, add:Boolean):void
	{
		if (!instance)
			return;
		
		for each(var alias:ComponentAliasInfo in classMetaData.componentAliases)
		{
			var type:Class = ToolKitUtil.getDefinition(alias.type) as Class;
			if (instance is type) 
			{
				if (add)
					this[alias.id] = instance;
				else
					this[alias.id] = null;
			}
		}
	}
	
	//----------------------------------
	//  [ModelAlias]
	//----------------------------------
	
	// TODO (mschmalle) addOrRemoveModelAliases() method seems implemented wrong
	
	/**
	 * @private
	 * Adds or removes the classMetaData.modelAliases to the behavior.
	 */	
	protected function addOrRemoveModelAliases(
		instance:IEventDispatcher, add:Boolean):void
	{
		if (!instance)
			return;
		
		// think about using component properties by type later
		// right now we check model manager for a layer, then check
		// the layer for the api
		
		var layer:IModelLayer = ModelManager.getModelLayer(instance);
		if (!layer)
			return;
		
		for each(var alias:ModelAliasInfo in classMetaData.modelAliases)
		{
			var type:Class = ToolKitUtil.getDefinition(alias.type) as Class;
			var model:IComponentModel = layer.getModel(type);
			
			// FIXME (mschmalle) unit test this method
			if (!model) // possibly a core not in the layer
			{
				if (alias.id in component)
				{
					model = component[alias.id];
				}
			}
			
			if (!model)
				continue;			
			
			if (add)
			{
				addOrRemoveModelHandlers(model, true);
				setModelAlias(type, model);
			}
			else
			{
				addOrRemoveModelHandlers(model, false);
				setModelAlias(type, null);
			}
		}
	}	
	
	/**
	 * @private
	 * Adds or removes the classMetaData.modelAliases to the behavior.
	 */	
	protected function setModelAlias(api:Class, model:IComponentModel):void
	{
		for each(var alias:ModelAliasInfo in classMetaData.modelAliases)
		{
			var type:Class = ToolKitUtil.getDefinition(alias.type) as Class;
			if (api === type) 
			{
				this[alias.id] = model;
			}
			else if (api === IComponentModelCore && model is type)
			{
				this[alias.id] = model; // setting a coreModel alias
			}
		}
	}
	
	//----------------------------------
	//  [SkinPartAlias]
	//----------------------------------
	
	/**
	 * @private
	 * Adds or removes the classMetaData.skinPartAliases to the behavior.
	 * 
	 * <p>Called when the actual component.skin is added to the display list
	 * of the component, thus all skin parts are theoretically ready.</p>
	 * 
	 * @param instance
	 * @param add
	 * 
	 * @uses #setPart()
	 * @uses #partAdded()
	 * @uses #partRemoved()
	 */
	protected function attachOrDetachSkinPartAliases(host:IEventDispatcher, add:Boolean):void
	{
		if (!host)
			return;
		
		for each (var contract:SkinPartAliasInfo in classMetaData.skinPartAliases) 
		{
			var api:Class;
			var name:String = contract.id;
			var type:String = contract.type;
			
			if (name in host) 
			{
				api =  ToolKitUtil.getDefinition(type) as Class;
				
				if (host[name] is api)
				{
					if (add)
					{
						setPart(name, host[name]);
						partAdded(name, this[name]);
					}
					else
					{
						partRemoved(name, this[name]);
						setPart(name, null);
					}
				}
			}
		}		
	}

	/**
	 * @private
	 * Sets the part reference on this behavior.
	 * 
	 * @param name
	 * @param reference
	 */
	protected function setPart(name:String, reference:Object):Boolean
	{
		if (reference)
			this[name] = reference;
		
		if (reference)
			addOrRemovePartHandlers(IEventDispatcher(reference), true);
		else
			addOrRemovePartHandlers(this[name], false);
		
		if (!reference)
			this[name] = null;
		
		return true;
	}
	
	//--------------------------------------------------------------------------
	//
	//  Private :: Handlers
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @private
	 */
	private function layerActivateHandler(event:ComponentLayerEvent):void
	{
		layerActivated(event.layer);
	}
	
	/**
	 * @private
	 */
	private function layerDeactivateHandler(event:ComponentLayerEvent):void
	{
		layerDeactivated(event.layer);
	}
	
	// TKA 
	/**
	 * @private
	 * Called from the <code>SkinnableComponent.skin</code> property.
	 * Note: this will be called before the new skin is added to the 
	 * component's display list.
	 */
	private function skinChangedHandler(event:Event):void
	{
		//var parent:SkinnableComponent = event.currentTarget as SkinnableComponent;
		var parent:ICoreSkinAware = event.currentTarget as ICoreSkinAware;
		
		if (parent && parent.coreSkin == null && oldSkin != null)
		{
			skinRemoved(oldSkin);
			oldSkin = null;
		}
		
		if (parent && parent.coreSkin)
		{
			// only return if this is a component that uses validateSkinAttachment()
			// otherwise this could just be a behavior attached to a spark component
			if (parent.coreSkin.parent == null && (component is IToolKitComponent))
				return;
			
			skinAdded(parent.coreSkin);
		}
		else if ("skin" in event.currentTarget)
		{
			// FIXME (mschmalle) Fix this in SparkComponentBehavior
			var skin:IEventDispatcher = Object(event.currentTarget).skin as IEventDispatcher;
			if (skin)
				skinAdded(skin);
		}
	}
	
	/**
	 * @private
	 */
	private function skinAddHandler(event:SkinEvent):void
	{
		skinAdded(event.skin);
	}
	
	/**
	 * @private
	 */
	private function skinRemoveHandler(event:SkinEvent):void
	{
		skinRemoved(event.skin);
	}
	
	/**
	 * @private
	 */
	private function chromeAddHandler(event:ChromeEvent):void
	{
		chromeAdded(IEventDispatcher(event.currentTarget));
	}
	
	/**
	 * @private
	 */
	private function chromeRemoveHandler(event:ChromeEvent):void
	{
		chromeRemoved(IEventDispatcher(event.currentTarget));
	}	
	
	/**
	 * @private
	 */
	private function behaviorAddHandler(event:BehaviorLayerEvent):void
	{
		behaviorAdded(event.api, event.behavior);
	}
	
	/**
	 * @private
	 */
	private function behaviorRemoveHandler(event:BehaviorLayerEvent):void
	{
		behaviorRemoved(event.api, event.behavior);
	}
	
	/**
	 * @private
	 */
	private function modelAddHandler(event:ModelLayerEvent):void
	{
		addOrRemoveModelHandlers(event.model, true);
		setModelAlias(event.api, event.model);
		modelAdded(event.api, event.model);
	}
	
	/**
	 * @private
	 */
	private function modelRemoveHandler(event:ModelLayerEvent):void
	{
		addOrRemoveModelHandlers(event.model, false);
		setModelAlias(event.api, null);
		modelRemoved(event.api, event.model);
	}
	
	/**
	 * @private
	 */
	protected function handleNotification(name:String):void
	{
	}
	
	/**
	 * @private
	 * 
	 * For now this is called from CoreComponentBehavior in the 
	 * skin_propertyChangeHandler() handler of the skin.
	 * 
	 * Note :: A property on a skin can be removed with removeElement()
	 * but that call alone will not trigger a PROPERTY_CHANGE event.
	 * The property on the skin must be de-referenced like;
	 * 
	 * skin.removeElement(skin.myProp);
	 * skin.myProp = null;
	 * 
	 * The above will trigger this handler.
	 * 
	 * TODO There has to be some type of wait to get better performance
	 * here by caching something
	 */
	protected function propertyChangeHandler(event:PropertyChangeEvent):void 
	{
		// FIXME (mschmalle) beta1
		handleNotification(event.property.toString());
	}	
	
}
}